Django at a glance
Because Django was developed in a fast-paced newsroom environment, it was designed to make common Web-development tasks fast and easy. Here's an informal overview of how to write a database-driven Web app with Django.
The goal of this document is to give you enough technical specifics to understand how Django works, but this isn't intended to be a tutorial or reference. Please see our more-detailed Django documentation when you're ready to start a project.
Design your model
Start by describing your database layout in Python code. Django's data-model API offers many rich ways of representing your models -- so far, it's been solving two years' worth of database-schema problems. Here's a quick example:
class Reporter(meta.Model):
full_name = meta.CharField(maxlength=70)
def __repr__(self):
return self.full_name
class Article(meta.Model):
pub_date = meta.DateTimeField()
headline = meta.CharField(maxlength=200)
article = meta.TextField()
reporter = meta.ForeignKey(Reporter)
def __repr__(self):
return self.headline
Install it
Next, run the Django command-line utility. It'll create the database tables for you automatically, in the database specified in your Django settings. Django works best with PostgreSQL, although we've recently added beta MySQL support and other database adapters are on the way:
django-admin.py install news
Enjoy the free API
With that, you've got a free, and rich, Python API to access your data. The API is created on the fly: No code generation necessary:
# Modules are dynamically created within django.models.
# Their names are plural versions of the model class names.
>>> from django.models.news import reporters, articles
# No reporters are in the system yet.
>>> reporters.get_list()
[]
# Create a new Reporter.
>>> r = reporters.Reporter(full_name='John Smith')
# Save the object into the database. You have to call save() explicitly.
>>> r.save()
# Now it has an ID.
>>> r.id
1
# Now the new reporter is in the database.
>>> reporters.get_list()
[John Smith]
# Fields are represented as attributes on the Python object.
>>> r.full_name
'John Smith'
# Django provides a rich database lookup API that's entirely driven by keyword arguments.
>>> reporters.get_object(id__exact=1)
John Smith
>>> reporters.get_object(full_name__startswith='John')
John Smith
>>> reporters.get_object(full_name__contains='mith')
John Smith
>>> reporters.get_object(id__exact=2)
Traceback (most recent call last):
...
django.models.news.ReporterDoesNotExist: Reporter does not exist for {'id__exact': 2}
# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to reporters.get_object(id__exact=1).
>>> reporters.get_object(pk=1)
John Smith
# Create an article.
>>> from datetime import datetime
>>> a = articles.Article(pub_date=datetime.now(), headline='Django is cool', article='Yeah.', reporter_id=1)
>>> a.save()
# Now the article is in the database.
>>> articles.get_list()
[Django is cool]
# Article objects get API access to related Reporter objects.
>>> r = a.get_reporter()
>>> r.full_name
'John Smith'
# And vice versa: Reporter objects get API access to Article objects.
>>> r.get_article_list()
[Django is cool]
# The API follows relationships as far as you need.
# Find all articles by a reporter whose name starts with "John".
>>> articles.get_list(reporter__full_name__startswith="John")
[Django is cool]
# Change an object by altering its attributes and calling save().
>>> r.full_name = 'Billy Goat'
>>> r.save()
# Delete an object with delete().
>>> r.delete()
A dynamic admin interface: It's not just scaffolding -- it's the whole house
Once your models are defined, Django can automatically create an administrative interface -- a Web site that lets authenticated users add, change and delete objects. It's as easy as adding an extra admin attribute to your model classes:
class Article(meta.Model):
pub_date = meta.DateTimeField()
headline = meta.CharField(maxlength=200)
article = meta.TextField()
reporter = meta.ForeignKey(Reporter)
class META:
admin = meta.Admin()
The philosophy here is that your site is edited by a staff, or a client, or maybe just you -- and you don't want to have to deal with creating backend interfaces just to manage content.
Our typical workflow at World Online is to create models and get the admin sites up and running as fast as possible, so our staff journalists can start populating data. Then we develop the way data is presented to the public.
Design your URLs
A clean, elegant URL scheme is an important detail in a high-quality Web application. Django lets you design URLs however you want, with no framework limitations.
To design URLs for an app, you create a Python module. For the above Reporter/Article example, here's what that might look like:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^/articles/(?P<year>\d{4})/$', 'myproject.news.views.year_archive'),
(r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'myproject.news.views.month_archive'),
(r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<article_id>\d+)/$', 'myproject.news.views.article_detail'),
)
The code above maps URLs, as regular expressions, to the location of Python callback functions (views). The regular expressions use parenthesis to "capture" values from the URLs. When a user requests a page, Django runs through each regular expression, in order, and stops at the first one that matches the requested URL. (If none of them matches, Django calls a special 404 view.) This is blazingly fast, because the regular expressions are compiled at load time.
Once one of the regexes matches, Django imports and calls the given view, which is a simple Python function. Each view gets passed a request object -- which contains request metadata and lets you access GET and POST data as simple dictionaries -- and the values captured in the regex, via keyword arguments.
For example, if a user requested the URL "/articles/2005/05/39323/", Django would call the function myproject.news.views.article_detail(request, year='2005', month='05', article_id='39323').
Write your views
Each view is responsible for doing one of two things: Returning an HttpResponse object containing the content for the requested page, or raising an exception such as Http404. The rest is up to you.
Generally, a view retrieves data according to the parameters, loads a template and renders the template with the retrieved data. Here's an example view for article_detail from above:
def article_detail(request, year, month, article_id):
# Use the Django API to find an object matching the URL criteria.
a = get_object_or_404(articles, pub_date__year=year, pub_date__month=month, pk=article_id)
return render_to_response('news/article_detail', {'article': a})
This example uses Django's template system, which has several key features.
Design your templates
The code above loads the news/article_detail template.
Django has a template search path, which allows you to minimize redundancy among templates. In your Django settings, you specify a list of directories to check for templates. If a template doesn't exist in the first directory, it checks the second, and so on.
Let's say the news/article_detail template was found. Here's what that might look like:
{% extends "base" %}
{% block title %}{{ article.headline }}{% endblock %}
{% block content %}
<h1>{{ article.headline }}</h1>
<p>By {{ article.get_reporter.full_name }}</p>
<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{{ article.article }}
{% endblock %}
It should look straightforward. Variables are surrounded by double-curly braces. {{ article.headline }} means "Output the value of the article's headline attribute." But dots aren't used only for attribute lookup: They also can do dictionary-key lookup, index lookup and function calls (as is the case with article.get_reporter).
Note {{ article.pub_date|date:"F j, Y" }} uses a Unix-style "pipe" (the "|" character). This is called a template filter, and it's a way to filter the value of a variable. In this case, the date filter formats a Python datetime object in the given format (as found in PHP's date function; yes, there is one good idea in PHP).
You can chain together as many filters as you'd like. You can write custom filters. You can write custom template tags, which run custom Python code behind the scenes.
Finally, Django uses the concept of template inheritance: That's what the {% extends "base" %} does. It means "First load the template called 'base', which has defined a bunch of blocks, and fill the blocks with the following blocks." In short, that lets you dramatically cut down on redundancy in templates: Each template has to define only what's unique to that template.
Here's what the "base" template might look like:
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<img src="sitelogo.gif" alt="Logo" />
{% block content %}{% endblock %}
</body>
</html>
Simplistically, it defines the look-and-feel of the site (with the site's logo), and provides "holes" for child templates to fill. This makes a site redesign as easy as changing a single file -- the base template.
Note that you don't have to use Django's template system if you prefer another system. While Django's template system is particularly well-integrated with Django's model layer, nothing forces you to use it. For that matter, you don't have to use Django's API, either. You can use another database abstraction layer, you can read XML files, you can read files off disk, or anything you want. Each piece of Django -- models, views, templates -- is decoupled from the next.
This is just the surface
This has been only a quick overview of Django's functionality. Some more useful features:
- A caching framework that integrates with memcached or other backends.
- A syndication framework that makes creating RSS and Atom feeds as easy as writing a small Python class.
- More sexy automatically-generated admin features -- this overview barely scratched the surface.
The next obvious steps are for you to download Django, read the tutorial and join the community. Thanks for your interest!
Comments
Arthur July 17, 2005 at 11:31 a.m.
Looking at what you have so far, it is really exciting. I would love to use this in my future projects.
I also like postgresql, but psycopg is a problem with me (it's GPL, and I can't use it for my work), and I don't have much experience with mysql. OTOH, I find Firebird to be just right. Are there any plan for it yet?
ArmedGeek July 17, 2005 at 2:50 p.m.
Astounding. Brilliant. Good Job. I absolutely intent to use this. All the tediousness is done without limiting the freedom of the presentation. AND it lets me stay sharp on my python skills.
Michael July 28, 2005 at 11:25 a.m.
If you intend to do a movie then I would like to recommend using Wink (http://www.debugmode.com/wink/). It is a free tool that makes it easy to capture your screen and generate a flash movie out of it. One thing I never liked with Rails is that their movies are in Quicktime *.mov format. Which is just a pain in the ass to install on Windows... But nearly everyone has flash.
Lars Marius Garshol July 31, 2005 at 3:20 p.m.
What do I do if I want to try Django with a database I already have? Can I say "build me the API from the DB"? Or, alternatively, create the same declarations you show above, and then say "build me the API (assuming the DB is there and that the declarations match)"?
Adrian Holovaty August 1, 2005 at 1:53 p.m.
Lars: That's on the to-do list. See http://code.djangoproject.com/ticket/90 .
Dark Cowherd August 8, 2005 at 9:33 a.m.
Any plans for a Firebird Interface. Can I get involved trying to get the Firebird interface working.
darkcowherd_at_gmail_dot_com
Walter August 24, 2005 at 6:24 p.m.
Is there a printer-friendly option for this documentation? It's really very annoying that I can't print this stuff without having the right side chopped off...
Paul Bissex August 29, 2005 at 8:09 p.m.
Along those lines I was thinking that it would be nice to distribute HTML versions of the doc pages along with the reStructuredText versions. The reST source could go in django_src/docs/txt and the html in django_src/docs/html, for example.
Straw Dogs September 27, 2005 at 5:58 p.m.
Been looking for a nice Python webdev platform recently and this fits in nicely. I've had a play round at home but I'll put it into use at work and report back. Given it the thumbs up over at my blog. Its nice, clean and simple but with a hell of a lot of power.
Keep up the good work - oh and get a release out as you'll reach a wider audience then.
Peter Odding October 27, 2005 at 9:09 p.m.
@Walter: For Mozilla and co. you can use the menu-option "View -> Page Style -> No Style" which should give you a printable page
David Franjkovic November 22, 2005 at 1:30 p.m.
nice application.
Post a comment
Note: Please only use the comments for questions/critcisms/suggestions on the docs; if you experience errors please file a ticket, ask in the IRC channel, or post to the django-users list. Comments will be periodically reviewed, integrated into the documentation proper, and removed.

Zoom.Quiet July 16, 2005 at 2:59 a.m.
grace Web Application frame!
we r the Chinese Python user,begin study the Django
this is the special topic Wiki Page:
http://wiki.woodpecker.org.cn/moin/DjanG...